x86: Emulated TSC should run at same (1GHz) rate in guest kernel and apps.
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 6 Oct 2009 09:09:21 +0000 (10:09 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 6 Oct 2009 09:09:21 +0000 (10:09 +0100)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/time.c
xen/include/asm-x86/domain.h

index f21861d7e68b84ad42c015f1f1bb6f4946749863..ef505024c6faa876fc0ea35f13b800f2f97c3e87 100644 (file)
@@ -837,17 +837,26 @@ void update_vcpu_system_time(struct vcpu *v)
     t = &this_cpu(cpu_time);
     u = &vcpu_info(v, time);
 
-    if ( u->tsc_timestamp == t->local_tsc_stamp )
-        return;
-
-    version_update_begin(&u->version);
-
-    u->tsc_timestamp     = t->local_tsc_stamp;
-    u->system_time       = t->stime_local_stamp;
-    u->tsc_to_system_mul = t->tsc_scale.mul_frac;
-    u->tsc_shift         = (s8)t->tsc_scale.shift;
-
-    version_update_end(&u->version);
+    if ( v->domain->arch.vtsc )
+    {
+        if ( u->tsc_timestamp == t->stime_local_stamp )
+            return;
+        version_update_begin(&u->version);
+        u->tsc_timestamp     = t->stime_local_stamp;
+        u->system_time       = t->stime_local_stamp;
+        u->tsc_to_system_mul = 0x80000000u;
+        u->tsc_shift         = 1;
+        version_update_end(&u->version);
+    }
+    else if ( u->tsc_timestamp != t->local_tsc_stamp )
+    {
+        version_update_begin(&u->version);
+        u->tsc_timestamp     = t->local_tsc_stamp;
+        u->system_time       = t->stime_local_stamp;
+        u->tsc_to_system_mul = t->tsc_scale.mul_frac;
+        u->tsc_shift         = (s8)t->tsc_scale.shift;
+        version_update_end(&u->version);
+    }
 }
 
 void update_domain_wallclock_time(struct domain *d)
@@ -1435,26 +1444,24 @@ struct tm wallclock_time(void)
 
 void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs)
 {
-    s_time_t now;
+    s_time_t now = get_s_time();
+
+    spin_lock(&v->domain->arch.vtsc_lock);
 
     if ( guest_kernel_mode(v, regs) )
-    {
         v->domain->arch.vtsc_kerncount++;
-        rdtsc(regs->eax, regs->edx);
-    }
     else
-    { 
-        v->domain->arch.vtsc_kerncount++;
-        spin_lock(&v->domain->arch.vtsc_lock);
-        now = get_s_time() + v->domain->arch.vtsc_stime_offset;
-        if ( (int64_t)(now - v->domain->arch.vtsc_last) > 0 )
-            v->domain->arch.vtsc_last = now;
-        else
-            now = ++v->domain->arch.vtsc_last;
-        spin_unlock(&v->domain->arch.vtsc_lock);
-        regs->eax = (uint32_t)now;
-        regs->edx = (uint32_t)(now >> 32);
-    }
+        v->domain->arch.vtsc_usercount++;
+
+    if ( (int64_t)(now - v->domain->arch.vtsc_last) > 0 )
+        v->domain->arch.vtsc_last = now;
+    else
+        now = ++v->domain->arch.vtsc_last;
+
+    spin_unlock(&v->domain->arch.vtsc_lock);
+
+    regs->eax = (uint32_t)now;
+    regs->edx = (uint32_t)(now >> 32);
 }
 
 /* vtsc may incur measurable performance degradation, diagnose with this */
index a608a87330f2d069df116bcc1625da5caa7d6307..27f1f82507e7bed1c3c65e5172ba379690515727 100644 (file)
@@ -306,7 +306,6 @@ struct arch_domain
     spinlock_t vtsc_lock;
     uint64_t vtsc_kerncount; /* for hvm, counts all vtsc */
     uint64_t vtsc_usercount; /* not used for hvm */
-    int64_t vtsc_stime_offset;
 } __cacheline_aligned;
 
 #define has_arch_pdevs(d)    (!list_empty(&(d)->arch.pdev_list))